#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/backlight.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/power_supply.h>
//#include <linux/video_output.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/jiffies.h>
#include <linux/miscdevice.h>
//#include <asm/bootinfo.h>
#include <linux/module.h>
#include <linux/device.h>
//#include <ec_it8528.h>

#include "../ec_it8733_inc/ec_it8733_dev.h"


//#define linux_outb outb
//#define linux_inb inb

unsigned char linux_inb(unsigned short int port);
void linux_outb( unsigned short int port, unsigned char value);

unsigned char linux_inb(unsigned short int port)
{
  return inb(port);
}
void linux_outb( unsigned short int port, unsigned char value)
{
  outb(value,port);
}




//static ssize_t ec_it8733_dev_config(unsigned char *ecram_vals);
static struct class  *ec_it8733_dev_class;
static struct device *ec_it8733_dev_class_dev;


static int ec_it8733_dev_open(struct inode *inode, struct file *file)
{
	return 0;
}



char strbuf[100]={0};
static long ec_it8733_dev_ioctl(struct file *file,
    unsigned int cmd, unsigned long arg)
{
  int i;
  int err = 0;
  void __user *uarg = (void __user *) arg;

  //printk("fdfsd\n");

  switch (cmd) 
  {
    case EC_DEV_IN:
    {
  #if 0  
      mutex_unlock(&rtc->ops_lock);

      err = rtc_read_alarm(rtc, &alarm);
      if (err < 0)
        return err;
  #endif
      if (copy_to_user(uarg, &strbuf, sizeof(strbuf)))
        err = -EFAULT;
      return err;
    }

    case EC_DEV_OUT:
    {
      

      if (copy_from_user(&strbuf, uarg, sizeof(strbuf)))
        return -EFAULT; 
      return err;
    }
#if 0
    case EC_DEV_TEST:
    {
      //unsigned short u16BaseAddr=0x9002;
      unsigned short u16BaseAddr=0x0290;

      int nCpuTemp; int nMainBoardTemp; int nChassisTemp;
      
      outb ( 0x29,u16BaseAddr + 0x05);
      nMainBoardTemp = inb ( u16BaseAddr + 0x06);

      outb ( 0x2A,u16BaseAddr + 0x05);
      nCpuTemp = inb ( u16BaseAddr + 0x06);

      outb ( 0x2B,u16BaseAddr + 0x05);
      nChassisTemp = inb ( u16BaseAddr + 0x06);

				printk(              "     CPU   temprature = %08d; \n",nCpuTemp );
				printk(  "main board temprature = %08d; \n",nMainBoardTemp );
				printk(                "   chassis temprature = %08d; \n",nChassisTemp );
				//mvprintw(              "CPU fan rotation rate = %08d; \n",nCpuFan );      

        printk("%s %s %d  rtc\n",__FILE__,__FUNCTION__,__LINE__);

        outb ( 0x52,u16BaseAddr + 0x05);
        nChassisTemp = inb ( u16BaseAddr + 0x06);

				printk(              "     0x52 = %08d; \n",nChassisTemp );


        for(i=0;i<15;i++)
        {
          u16BaseAddr=0x70;
          unsigned char u8rtc;
          outb ( i,u16BaseAddr);
          u8rtc = inb ( u16BaseAddr+1 );
          printk( " %02X ", u8rtc );
        }
        printk("  rtc\n");


      //dev_outb (fd, 0x2B,u16BaseAddr + 0x05);
      //nChassisTemp = dev_inb (fd, u16BaseAddr + 0x06);

      return err;             
    }
#endif

    case EC_DEV_BYTE_IN:
    {
      typEcDev ecdev;
      	//printk(              "     CPU   temprature = %08d; \n",93 );

      if (copy_from_user(&ecdev, uarg, sizeof(ecdev)))
        return -EFAULT; 
      ecdev.value=inb(ecdev.port);
      printk(" in ecdev.value=%02X; ecdev.port =%04X\n", ecdev.value ,ecdev.port);
      if (copy_to_user(uarg, &ecdev, sizeof(ecdev)))
        return -EFAULT; 
      return 0;    
    }

    case EC_DEV_BYTE_OUT:
    {
      typEcDev ecdev;
      if (copy_from_user(&ecdev, uarg, sizeof(ecdev)))
        return -EFAULT; 


      outb(ecdev.value,ecdev.port);
      printk(" out ecdev.value=%02X; ecdev.port =%04X\n", ecdev.value ,ecdev.port);
      return 0;   
    }


  }
  return err;
}



ssize_t ec_it8733_dev_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
	unsigned char ecram_vals[256];
	//unsigned int i;
#if 0
	for(i = 0; i < 256;i++)
	{
		ecram_vals[i] = it8528_read(i);
	}
#endif
	memset(ecram_vals, 0xFF, sizeof(ecram_vals));
	//ec_it8733_dev_config(&ecram_vals[0]);

  if(copy_to_user(buf, ecram_vals, sizeof(ecram_vals)))
    return -EFAULT; 

	return sizeof(ecram_vals);
}

static ssize_t ec_it8733_dev_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
	int val;	

	if(copy_from_user(&val, buf, count))
    return -EFAULT; 


	//it8528_write((val>>8)&0xff , val&0xff);
	
	return 0;
}

#if 0
static VOID EnterConfigMode (VOID  )
{
  UINT8  PnpKey;

  PnpKey = 0x87;
  linux_outb(SIO_CONFIG_PORT, PnpKey);
  PnpKey = 0x01;
  linux_outb(SIO_CONFIG_PORT, PnpKey);
  PnpKey = 0x55;
  linux_outb(SIO_CONFIG_PORT, PnpKey);
  PnpKey = 0x55;
  linux_outb(SIO_CONFIG_PORT, PnpKey);
  
  return;
}

static VOID ExitConfigMode (  VOID  )
{
  UINT8  RegData = 0x00;

  linux_outb (LPC_EC_INDEX_PORT, SIO_CONFIG_CTRL);
  RegData = linux_inb (LPC_EC_DATA_PORT) | BIT1;
  linux_outb (LPC_EC_INDEX_PORT, SIO_CONFIG_CTRL);  
  linux_outb (LPC_EC_DATA_PORT, RegData);
  
  return;
}

static ssize_t ec_it8733_dev_config(unsigned char *ecram_vals)
{
    int i;
	unsigned char Chipid0,Chipid1 =0;
	UINT16  DataTemp;
  EnterConfigMode();
  EnterConfigMode();
  linux_outb (LPC_EC_INDEX_PORT, 0x20);  
  Chipid0 = linux_inb (LPC_EC_DATA_PORT);
  ecram_vals[0]=Chipid0;

  linux_outb (LPC_EC_INDEX_PORT, 0x21);
  Chipid1 = linux_inb (LPC_EC_DATA_PORT); 
  ecram_vals[1]=Chipid1;

  linux_outb (LPC_EC_INDEX_PORT, 0x22);
  ecram_vals[2] = linux_inb (LPC_EC_DATA_PORT);

#if  0
  linux_outb (LPC_EC_INDEX_PORT, 0x22);
  linux_outb (LPC_EC_DATA_PORT,0xF5);
  linux_outb (LPC_EC_INDEX_PORT, 0x22);
  ecram_vals[3] = linux_inb (LPC_EC_DATA_PORT);
#endif

  for(i=0;i<15;i++)
  {
    linux_outb (LPC_EC_INDEX_PORT, 0x07);
    linux_outb (LPC_EC_DATA_PORT, 0x00);

    linux_outb (LPC_EC_INDEX_PORT, i);

      ecram_vals[0x20+i] = linux_inb (LPC_EC_DATA_PORT);

  }

  //DEBUG((EFI_D_ERROR, "Lyang: In Ls7a.c, line %d. Chipid0 %x Chipid1 %x\n", __LINE__,Chipid0,Chipid1));
  linux_outb (LPC_EC_INDEX_PORT, 0x7);  
  linux_outb (LPC_EC_DATA_PORT, 0x7);  
  linux_outb (LPC_EC_INDEX_PORT, 0x62); 
  linux_outb (LPC_EC_DATA_PORT, 0x04);  
  linux_outb (LPC_EC_INDEX_PORT, 0x63); 
  linux_outb (LPC_EC_DATA_PORT, 0x00); 
  linux_outb (LPC_EC_INDEX_PORT, 0x27);  
  DataTemp = linux_inb (LPC_EC_DATA_PORT);
  ecram_vals[0x10]=DataTemp;
  //DEBUG((EFI_D_ERROR, "Lyang: In EncryDriverPei.c, line %d.Data0 0x%x \n", __LINE__,Data0));
  linux_outb (LPC_EC_INDEX_PORT, 0x27);  
  linux_outb (LPC_EC_DATA_PORT, DataTemp|0x38); 
  linux_outb (LPC_EC_INDEX_PORT, 0xC2); 
  DataTemp = linux_inb (LPC_EC_DATA_PORT);
  ecram_vals[0x11]=DataTemp;
  //DEBUG((EFI_D_ERROR, "Lyang: In EncryDriverPei.c, line %d.Data0 0x%x \n", __LINE__,Data0));
  linux_outb (LPC_EC_INDEX_PORT, 0xC2);  
  linux_outb (LPC_EC_DATA_PORT, DataTemp|0x08);  
  linux_outb (LPC_EC_INDEX_PORT, 0xCA); 
  DataTemp = linux_inb (LPC_EC_DATA_PORT);
  ecram_vals[0x12]=DataTemp;
  //DEBUG((EFI_D_ERROR, "Lyang: In EncryDriverPei.c, line %d.Data1 0x%x \n", __LINE__,Data1));
//Output settings
  linux_outb (LPC_EC_INDEX_PORT, 0xCA);  
  linux_outb (LPC_EC_DATA_PORT, DataTemp|0x08);  
  DataTemp = linux_inb(0x402);
  ecram_vals[0x13]=DataTemp;
  printk("%02X \n",DataTemp);
  linux_outb (0x402, (DataTemp | 0x08));
  ExitConfigMode();	
  return 0;
}
#endif

static struct file_operations ec_it8733_dev_fops = {
    .owner  =   THIS_MODULE,    /* ����һ���꣬�������ģ��ʱ�Զ�������__this_module���� */
    .open   =   ec_it8733_dev_open,     
	.read	=	ec_it8733_dev_read,	  
	.write	=	ec_it8733_dev_write,
  //.ioctl  = ec_it8733_dev_ioctl,	
  .unlocked_ioctl  =ec_it8733_dev_ioctl,
};


int major;
static int ec_it8733_dev_init(void)
{
	major = register_chrdev(0, "ec_it8733_dev", &ec_it8733_dev_fops); // ע��, �����ں�

	ec_it8733_dev_class = class_create(THIS_MODULE, "ecit8733dev");

	ec_it8733_dev_class_dev = device_create(ec_it8733_dev_class, NULL, MKDEV(major, 0), NULL, "ec_it8733"); /* /dev/ecit8733*/


	return 0;
}

static void ec_it8733_dev_exit(void)
{
	unregister_chrdev(major, "ec_it8733_dev");
	device_unregister(ec_it8733_dev_class_dev);
	class_destroy(ec_it8733_dev_class);
}


module_init(ec_it8733_dev_init);

module_exit(ec_it8733_dev_exit);

MODULE_LICENSE("GPL");

